package com.qijian.common.utils.file;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import com.qijian.common.config.QiJianConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;


public class AliyunOSSUtil {

    private static final Logger logger = LoggerFactory.getLogger(AliyunOSSUtil.class);

    // 区域
    private final static String ENDPOINT = "https://oss-cn-shanghai.aliyuncs.com";
    // 访问地址-内网
//    private final static String ENDPOINT_INTRANET = "https://Bucket.oss-cn-shanghai-internal.aliyuncs.com";
    // 访问地址-外网
    private final static String ENDPOINT_EXTRANET = "https://Bucket.oss-cn-shanghai.aliyuncs.com";

    // id
    private final static String ACCESSKEY_ID = "LTAI4GAqXpkRkR3hnVrSfrvB";
    // key
    private final static String ACCESSKEY_SECRET = "CLCMpTKIkMdzADolyaZEIW7m9I2pD0";
    // bucket
    private final static String BUCKET_NAME = "qj-emanufacture";




    /**
     * 获取阿里云OSS客户端对象
     *
     * @return ossClient
     */
    public static OSS getOSSClient() {
        return new OSSClientBuilder().build(ENDPOINT, ACCESSKEY_ID, ACCESSKEY_SECRET);
    }

    /**
     * 创建存储空间
     *
     * @param ossClient  OSS连接
     * @param bucketName 存储空间
     * @return /
     */
    public static String createBucketName(OSS ossClient, String bucketName) {
        // 存储空间
        if (!ossClient.doesBucketExist(bucketName)) {
            // 创建存储空间
            Bucket bucket = ossClient.createBucket(bucketName);
            logger.info("创建存储空间成功");
            return bucket.getName();
        }
        ossClient.shutdown();
        return bucketName;
    }

    /**
     * 删除存储空间buckName
     *
     * @param ossClient  oss连接
     * @param bucketName 存储空间
     */
    public static void deleteBucket(OSS ossClient, String bucketName) {
        ossClient.deleteBucket(bucketName);
        ossClient.shutdown();
        logger.info("删除{}Bucket成功", bucketName);
    }

    /**
     * 创建模拟文件夹
     *
     * @param ossClient  oss连接
     * @param bucketName 存储空间
     * @param folder     模拟文件夹名如"qj_suzhou/"
     * @return 文件夹名
     */
    public static String createFolder(OSS ossClient, String bucketName, String folder) {
        // 文件夹名
        // 判断文件夹是否存在，不存在则创建
        if (!ossClient.doesObjectExist(bucketName, folder)) {
            // 创建文件夹
            ossClient.putObject(bucketName, folder, new ByteArrayInputStream(new byte[0]));
            logger.info("创建文件夹成功");
            // 得到文件夹名
            OSSObject object = ossClient.getObject(bucketName, folder);
            return object.getKey();
        }
        ossClient.shutdown();
        return folder;
    }

    /**
     * 根据路径删除OSS服务器上的文件
     *
     * @param ossClient oss连接
     * @param url       文件路径
     */
    public static void deleteFile(OSS ossClient, String url) {
        String baseUrl = ENDPOINT_EXTRANET.replace("Bucket", BUCKET_NAME);
        String fileName = url.substring(url.indexOf(baseUrl) + baseUrl.length() + 1);
        ossClient.deleteObject(BUCKET_NAME, fileName);
        ossClient.shutdown();
        logger.info("删除{}下的文件{}成功", BUCKET_NAME, fileName);
    }

    /**
     * 上传文件至OSS
     *
     * @param ossClient oss连接
     * @param file      上传文件（文件全路径如：D:\\image\\cake.jpg）
     * @param folder    模拟文件夹名 如"qj_suzhou/"
     * @return String 返回的唯一MD5数字签名
     */
    @SuppressWarnings("finally")
    public static String uploadObject2OSS(OSS ossClient, MultipartFile file, String folder, String fileName) {
        if (!ossClient.doesBucketExist(BUCKET_NAME)) {
            createBucketName(ossClient, BUCKET_NAME);
        }
        String resultStr = null;
        try {
            // 以输入流的形式上传文件
            InputStream is = file.getInputStream();
            // 文件大小
            long fileSize = file.getSize();
            // 创建上传Object的Metadata
            ObjectMetadata metadata = new ObjectMetadata();
            // 上传的文件的长度
            metadata.setContentLength(is.available());
            // 指定该Object被下载时的网页的缓存行为
            metadata.setCacheControl("no-cache");
            // 指定该Object下设置Header
            metadata.setHeader("Pragma", "no-cache");
            // 指定该Object被下载时的内容编码格式
            metadata.setContentEncoding("utf-8");
            // 文件的MIME，定义文件的类型及网页编码，决定浏览器将以什么形式、什么编码读取文件。如果用户没有指定则根据Key或文件名的扩展名生成，
            // 如果没有扩展名则填默认值application/octet-stream
//            metadata.setContentType(getContentType(fileName));
            // 指定该Object被下载时的名称（指示MINME用户代理如何显示附加的文件，打开或下载，及文件名称）
            metadata.setContentDisposition("filename/filesize=" + fileName + "/" + fileSize + "Byte.");
            // 上传文件 (上传文件流的形式)
            PutObjectResult putResult = ossClient.putObject(new PutObjectRequest(BUCKET_NAME, folder + "/" + fileName, is, metadata));
            // 解析结果
            resultStr = putResult.getETag();
            logger.error("request ID:", putResult.getETag());

            resultStr = ENDPOINT_EXTRANET.replace("Bucket", BUCKET_NAME) + "/" + folder + "/" + fileName;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("上传阿里云OSS服务器异常." + e.getMessage(), e);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
            return resultStr;
        }
    }

    public static String uploadObject2OSS(OSS ossClient, File file, String folder, String fileName) {
        if (!ossClient.doesBucketExist(BUCKET_NAME)) {
            createBucketName(ossClient, BUCKET_NAME);
        }
        String resultStr = null;
        try {
            // 以输入流的形式上传文件
            InputStream is = new FileInputStream(file);
            // 文件大小
            long fileSize = file.length();
            // 创建上传Object的Metadata
            ObjectMetadata metadata = new ObjectMetadata();
            // 上传的文件的长度
            metadata.setContentLength(is.available());
            // 指定该Object被下载时的网页的缓存行为
            metadata.setCacheControl("no-cache");
            // 指定该Object下设置Header
            metadata.setHeader("Pragma", "no-cache");
            // 指定该Object被下载时的内容编码格式
            metadata.setContentEncoding("utf-8");
            // 文件的MIME，定义文件的类型及网页编码，决定浏览器将以什么形式、什么编码读取文件。如果用户没有指定则根据Key或文件名的扩展名生成，
            // 如果没有扩展名则填默认值application/octet-stream
//            metadata.setContentType(getContentType(fileName));
            // 指定该Object被下载时的名称（指示MINME用户代理如何显示附加的文件，打开或下载，及文件名称）
            metadata.setContentDisposition("filename/filesize=" + fileName + "/" + fileSize + "Byte.");
            // 上传文件 (上传文件流的形式)
            PutObjectResult putResult = ossClient.putObject(new PutObjectRequest(BUCKET_NAME, folder + "/" + fileName, is, metadata));
            // 解析结果
            resultStr = putResult.getETag();
            logger.error("request ID:", putResult.getETag());

            resultStr = ENDPOINT_EXTRANET.replace("Bucket", BUCKET_NAME) + "/" + folder + "/" + fileName;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("上传阿里云OSS服务器异常." + e.getMessage(), e);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
            return resultStr;
        }
    }

    public static String uploadObject2OSS(OSS ossClient, InputStream is, String folder, String fileName) {
        if (!ossClient.doesBucketExist(BUCKET_NAME)) {
            createBucketName(ossClient, BUCKET_NAME);
        }
        String resultStr = null;
        try {
            // 以输入流的形式上传文件
            // 文件大小
            long fileSize = is.available();
            // 创建上传Object的Metadata
            ObjectMetadata metadata = new ObjectMetadata();
            // 上传的文件的长度
            metadata.setContentLength(is.available());
            // 指定该Object被下载时的网页的缓存行为
            metadata.setCacheControl("no-cache");
            // 指定该Object下设置Header
            metadata.setHeader("Pragma", "no-cache");
            // 指定该Object被下载时的内容编码格式
            metadata.setContentEncoding("utf-8");
            // 文件的MIME，定义文件的类型及网页编码，决定浏览器将以什么形式、什么编码读取文件。如果用户没有指定则根据Key或文件名的扩展名生成，
            // 如果没有扩展名则填默认值application/octet-stream
//            metadata.setContentType(getContentType(fileName));
            // 指定该Object被下载时的名称（指示MINME用户代理如何显示附加的文件，打开或下载，及文件名称）
            metadata.setContentDisposition("filename/filesize=" + fileName + "/" + fileSize + "Byte.");
            // 上传文件 (上传文件流的形式)
            PutObjectResult putResult = ossClient.putObject(new PutObjectRequest(BUCKET_NAME, folder + "/" + fileName, is, metadata));
            // 解析结果
            resultStr = putResult.getETag();
            resultStr = ENDPOINT_EXTRANET.replace("Bucket", BUCKET_NAME) + "/" + folder + "/" + fileName;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("上传阿里云OSS服务器异常." + e.getMessage(), e);
        } finally {
            ossClient.shutdown();
        }
        return resultStr;
    }

    public static String uploadObject2OSSWithWaterMark(OSS ossClient, MultipartFile file, String folder, String fileName) {
        if (!ossClient.doesBucketExist(BUCKET_NAME)) {
            createBucketName(ossClient, BUCKET_NAME);
        }
        String resultStr = null;


        try (InputStream inputStream = file.getInputStream();
             ByteArrayOutputStream os = new ByteArrayOutputStream();) {

            Image srcImg = ImageIO.read(inputStream);
            // add by chenxin  start   给图片加上水印
            Font font = new Font("微软雅黑", Font.PLAIN, 60);                     //水印字体
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
            String waterMarkContent = sdf.format(new Date());  //水印内容
            Color color = new Color(255, 0, 0, 255);
            if (srcImg != null) {
                int srcImgWidth = srcImg.getWidth(null);//获取图片的宽
                int srcImgHeight = srcImg.getHeight(null);//获取图片的高
                // 加水印
                BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
                Graphics2D g = bufImg.createGraphics();
                g.drawImage(srcImg, 1, 2, srcImgWidth, srcImgHeight, null);

                g.setColor(color); //根据图片的背景设置水印颜色
                g.setFont(font);              //设置字体
                g.drawString(waterMarkContent, 20, 60);  //画出水印
                g.dispose();
                ImageIO.write(bufImg, "jpg", os);
                bufImg.flush();
                try (InputStream input = new ByteArrayInputStream(os.toByteArray())) {

                    PutObjectResult putResult = ossClient.putObject(new PutObjectRequest(BUCKET_NAME, folder + "/" + fileName, input));
                    // 解析结果
                    resultStr = putResult.getETag();
                    resultStr = ENDPOINT_EXTRANET.replace("Bucket", BUCKET_NAME) + "/" + folder + "/" + fileName;
                    return resultStr;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return resultStr;
    }

    /**
     * base64文件上传阿里云
     *
     * @param ossClient oss连接
     * @param folder    模拟文件夹名
     * @param map       数据
     * @return /
     */
    @SuppressWarnings("finally")
    public String uploadBase64ToOSS(OSS ossClient, String folder, Map<String, Object> map) {
        if (!ossClient.doesBucketExist(BUCKET_NAME)) {
            createBucketName(ossClient, BUCKET_NAME);
        }
        InputStream inputStream;
        String newUrl = null;
        try {
            inputStream = new ByteArrayInputStream((byte[]) map.get("data"));
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(inputStream.available());
            // 指定该Object被下载时的内容编码格式
            metadata.setContentEncoding("utf-8");
            PutObjectResult putResult = ossClient.putObject(BUCKET_NAME, folder + map.get("fileName"), inputStream,
                    metadata);
            logger.error("request ID:", putResult.getETag());
            newUrl = ENDPOINT_EXTRANET.replace("Bucket", BUCKET_NAME) + "/" + folder + map.get("fileName");
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("上传阿里云OSS服务器异常.{}", e.getMessage(), e);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
            return newUrl;
        }
    }

    public static String fileDownload(String basePath, String fileName) {
        String objectName = fileName.replaceAll(ENDPOINT_EXTRANET.replace("Bucket", BUCKET_NAME) + File.separator, "");
//        String objectName = fileName.replaceAll(ENDPOINT_EXTRANET.replace("Bucket", BUCKET_NAME), "");
        OSS ossClient = getOSSClient();
        // 调用ossClient.getObject返回一个OSSObject实例，该实例包含文件内容及文件元信息。
        //OSSObject ossObject = ossClient.getObject(bucketName, objectName);
        // 调用ossObject.getObjectContent获取文件输入流，可读取此输入流获取其内容。
        // InputStream content = ossObject.getObjectContent();
        //指定文件保存路径
        String filePath = basePath + "/" + objectName.substring(0, objectName.lastIndexOf("/"));
        //判断文件目录是否存在，不存在则创建
        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();
        }
        //判断保存文件名是否加后缀
        if (objectName.contains(".")) {
            //指定文件保存名称
            filePath = filePath + "/" + objectName.substring(objectName.lastIndexOf("/") + 1);
        }
        //获取OSS文件并保存到本地指定路径中，此文件路径一定要存在，若保存目录不存在则报错，若保存文件名已存在则覆盖本地文件
        ossClient.getObject(new GetObjectRequest(BUCKET_NAME, objectName), new File(filePath));
        // 关闭OSSClient。
        ossClient.shutdown();
        return filePath;
    }

    public static String fileDownloadWithFolder(String basePath, String folder, String fileName) {
        String objectName = fileName.replaceAll(ENDPOINT_EXTRANET.replace("Bucket", BUCKET_NAME) + File.separator, "");
//        String objectName = fileName.replaceAll(ENDPOINT_EXTRANET.replace("Bucket", BUCKET_NAME), "");
        OSS ossClient = getOSSClient();
        // 调用ossClient.getObject返回一个OSSObject实例，该实例包含文件内容及文件元信息。
        //OSSObject ossObject = ossClient.getObject(bucketName, objectName);
        // 调用ossObject.getObjectContent获取文件输入流，可读取此输入流获取其内容。
        // InputStream content = ossObject.getObjectContent();
        //指定文件保存路径
        String filePath = basePath + "/" + folder;
        //判断文件目录是否存在，不存在则创建
        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();
        }
        //判断保存文件名是否加后缀
        if (objectName.contains(".")) {
            //指定文件保存名称
            filePath = filePath + "/" + objectName.substring(objectName.lastIndexOf("/") + 1);
        }
        //获取OSS文件并保存到本地指定路径中，此文件路径一定要存在，若保存目录不存在则报错，若保存文件名已存在则覆盖本地文件
        ossClient.getObject(new GetObjectRequest(BUCKET_NAME, objectName), new File(filePath));
        // 关闭OSSClient。
        ossClient.shutdown();
        return filePath;
    }

    public static String fileDownload(String basePath, String path, String fileName) {
        String objectName = path.replaceAll(ENDPOINT_EXTRANET.replace("Bucket", BUCKET_NAME) + File.separator, "");
        OSS ossClient = getOSSClient();
        //指定文件保存路径
        String filePath = basePath + "/" + objectName.substring(0, objectName.lastIndexOf("/"));
        //判断文件目录是否存在，不存在则创建
        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();
        }
        //判断保存文件名是否加后缀
        if (fileName.contains(".")) {
            //指定文件保存名称
            filePath = filePath + "/" + fileName.substring(fileName.lastIndexOf("/") + 1);
        }
        //获取OSS文件并保存到本地指定路径中，此文件路径一定要存在，若保存目录不存在则报错，若保存文件名已存在则覆盖本地文件
        ossClient.getObject(new GetObjectRequest(BUCKET_NAME, objectName), new File(filePath));
        // 关闭OSSClient。
        ossClient.shutdown();
        return filePath;
    }

    public static String localDownload(String fileNamePath) {
        String fileName = fileNamePath.substring(fileNamePath.lastIndexOf("/") + 1);
        String objectName = fileNamePath.substring(fileNamePath.indexOf(".com/") + 5);
        String path = QiJianConfig.getDownloadPath() + fileName;
        try {
            // 创建 OSSClient 实例
            OSS ossClient = getOSSClient();
            // 下载Object到本地文件，并保存到指定的本地路径中。如果指定的本地文件存在会覆盖，不存在则新建。
            // 如果未指定本地路径，则下载后的文件默认保存到示例程序所属项目对应本地路径中。
            ossClient.getObject(new GetObjectRequest(BUCKET_NAME, objectName), new File(path));
            // 关闭OSSClient。
            ossClient.shutdown();
        } catch (Exception e) {
            e.printStackTrace();
            e.fillInStackTrace();
        }
        return path;
    }
}
